﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ibba.agil.core.common;


namespace ibba.agil.core
{
    internal class EntityWhere : List<string> 
    {
        private 
            EntityData _entity;

        public EntityWhere(EntityData data) 
        {
            _entity = data;
            this.Add("WHERE 1=1 \n");
        }

        public EntityWhere()
        {
            this.Add("WHERE 1=1 \n");
        }

 
        private void Add() { }

        internal EntityData GetEntity
        {
            get { return _entity; }
        }


        public void Equal(LogicalOperator logic, string propName)
        {
            string metaName;
            object propertyValue;
            ExtractAttr(propName, out metaName,  out propertyValue);
            this.Add(string.Format("{0} {1}='{2}' \n", buildWhereLogic(logic), metaName, propertyValue));
        }

        public void Equal(LogicalOperator logic, string columnIdentifier , object propValue)
        {
            this.Add(string.Format("{0} {1}='{2}' \n", buildWhereLogic(logic), columnIdentifier, propValue));
        }


        public void Equal(string propName)
        {
            object propertyValue;
            string metaName;
            ExtractAttr(propName, out metaName, out propertyValue);
            this.Add(string.Format("AND {0}='{1}' \n", metaName, propertyValue));
        }

        //private void ExtractAttr(Type propType)
        //{

        //    var attr = propType.GetCustomAttributes(true);
        //}

        private void ExtractAttr(string propName, out string metaName,  out object propertyValue)
        {
            var property = _entity.GetType().GetProperty(propName);
            metaName = _entity.Mapper[propName];
            propertyValue = Internal.EntitySqlLanguage.AttributesBuilder(_entity, property);
        }

        public void MoreThan(LogicalOperator logic, string attribute, object valor)
        {
            this.Add(string.Format("{0} {1} >= {2} \n", buildWhereLogic(logic), attribute, valor));
        }

        public void MoreThan(string attribute, object valor)
        {
            this.Add(string.Format("AND {0} >= {1} \n", attribute, valor));
        }

        public void Like(LogicalOperator logic, string attribute, object valor)
        {

            this.Add(string.Format("{0} {1} like '{2}' \n", buildWhereLogic(logic), attribute, valor));
        }

        public void Like(string attribute, object valor)
        {
            this.Add(string.Format("AND {0} like '{1}' \n", attribute, valor));
        }

        public void Like(EntityData e, LikePattern percent, object propertyValue)
        {

            switch (percent)
            {
                case LikePattern.Right:
                    propertyValue = String.Concat(propertyValue, "%");
                    break;
                case LikePattern.Left:
                    propertyValue = String.Concat("%", propertyValue);
                    break;
                case LikePattern.Both:
                    propertyValue = String.Concat("%", propertyValue, "%");
                    break;
            }
            this.Add(string.Format("AND {0} like '{1}' \n", e.Mapper[e.GetType().Name], propertyValue));
        }

        public void In(string attribute, List<string> valor)
        {
            this.Add(string.Format(" AND {0} IN ({1})", attribute, String.Concat(valor)));
        }

        private string buildWhereLogic(LogicalOperator logic)
        {
            return (logic == LogicalOperator.AND) ? "AND " :
                             (logic == LogicalOperator.IN) ? "IN " : "OR ";
        }

        internal string build()
        {
            var str = new StringBuilder();
            this.ForEach(criteria => 
                            str.Append(criteria));
            return str.ToString();
        }
    }
}
